package com.baosight.risk.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author duanyongqiang
 * <p>
 * 日期工具类
 */
@Slf4j
public class DateUtils {

    /**
     * yyyyMMdd格式
     */
    public static final String YYYYMMDD = "yyyyMMdd";
    /**
     * yyyyMMddHHmmss格式
     */
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    /**
     * yyyy-MM-dd格式
     */
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    /**
     * yyyy-MM-dd HH:mm:ss格式
     */
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    /**
     * HHmmss格式
     */
    public static final String HHMMSS = "HHmmss";

    /**
     * HH:mm:ss格式
     */
    public static final String HH_MM_SS = "HH:mm:ss";

    /**
     * 系统默认ZoneId
     */
    public static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();

    /**
     * 根据formatter格式化日期为指定格式
     *
     * @param date
     * @param formatter
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String format(Date date, String formatter) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);
        return sdf.format(date);
    }

    /**
     * 根据字符串解析为日期
     *
     * @param dateStr
     * @param formatter
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static Date parse(String dateStr, String formatter) {
        if (StringUtils.isBlank(dateStr)) return null;
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            log.info("格式化日期出错!date={},formatter={},{}", dateStr, formatter, e);
        }
        return null;
    }

    /**
     * 格式化成yyyyMMdd形式
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String formatYYYYMMDD(Date date) {
        return format(date, YYYYMMDD);
    }

    /**
     * 格式化成yyyy-MM-dd形式
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String formatYYYY_MM_DD(Date date) {
        return format(date, YYYY_MM_DD);
    }

    /**
     * 格式化成yyyyMMddHHmmss形式
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String formatYYYYMMDDHHMMSS(Date date) {
        return format(date, YYYYMMDDHHMMSS);
    }

    /**
     * 格式化成yyyy-MM-dd HH:mm:ss形式
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String formatYYYY_MM_DD_HH_MM_SS(Date date) {
        return format(date, YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 格式化成HHmmss格式
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String formatHHMMSS(Date date) {
        return format(date, HHMMSS);
    }

    /**
     * 格式化成HH:mm:ss格式
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static String formatHH_MM_SS(Date date) {
        return format(date, HH_MM_SS);
    }

    /**
     * LocalDate转date
     *
     * @param localDate
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static Date toDate(LocalDate localDate) {
        if (localDate == null) return null;
        return Date.from(localDate.atStartOfDay(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * LocalDateTime转date
     *
     * @param localDateTime
     * @return
     * @author bazhandao
     * @date 2019-11-10
     */
    public static Date toDate(LocalDateTime localDateTime) {
        if (localDateTime == null) return null;
        return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * Date转LocalDate
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static LocalDate toLocalDate(Date date) {
        if (date == null) return null;
        return LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID).toLocalDate();
    }

    /**
     * Date转LocalDateTime
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        if (date == null) return null;
        return LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID);
    }

    /**
     * Date转LocalTime
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static LocalTime toLocalTime(Date date) {
        if (date == null) return null;
        return LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID).toLocalTime();
    }

    /**
     * 日期加上指定天数
     *
     * @param date
     * @param days
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static Date plusDays(Date date, int days) {
        if (date == null) return null;
        LocalDateTime localDateTime = toLocalDateTime(date);
        localDateTime = localDateTime.plusDays(days);
        return toDate(localDateTime);
    }

    /**
     * 日期减去指定天数
     *
     * @param date
     * @param days
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static Date minusDays(Date date, int days) {
        if (date == null) return null;
        LocalDateTime localDateTime = toLocalDateTime(date);
        localDateTime = localDateTime.minusDays(days);
        return toDate(localDateTime);
    }

    /**
     * 舍去时间，只保留日期
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static Date getDate(Date date) {
        if (date == null) return null;
        LocalDate localDate = toLocalDate(date);
        return toDate(localDate);
    }

    /**
     * 舍去年月日，只保留时间
     *
     * @param date
     * @return
     * @author bazhandao
     * @date 2018-11-10
     */
    public static Date getTime(Date date) {
        LocalTime localTime = toLocalTime(date);
        LocalDateTime localDateTime = LocalDateTime.of(LocalDate.of(0, 0, 0), localTime);
        return toDate(localDateTime);
    }

    /**
     * 根据当前日期获取季度
     *
     * @return
     * @author 黎秋荣
     * @date 2019-06-28
     */
    public static String getQuarter(Date date) {
        String data = DateUtils.format(date, "MM");
        //获取当年季度
        Integer mouth = Integer.valueOf(data);
        String quarterCurrent = "";
        if (mouth < 4) {
            quarterCurrent = "1";
        } else if (mouth > 3 && mouth < 7) {
            quarterCurrent = "2";
        } else if (mouth > 6 && mouth < 10) {
            quarterCurrent = "3";
        } else {
            quarterCurrent = "4";
        }
        return quarterCurrent;
    }

    /**
     * 根据当前日期获取季度
     *
     * @return
     * @author 黎秋荣
     * @date 2019-06-28
     */
    public static void getQuarterMouth(Integer quarterCurrent, List<String> mouth) {
        if (1 == quarterCurrent) {
            mouth.add("01");
            mouth.add("02");
            mouth.add("03");
        } else if (2 == quarterCurrent) {
            mouth.add("04");
            mouth.add("05");
            mouth.add("06");
        } else if (3 == quarterCurrent) {
            mouth.add("07");
            mouth.add("08");
            mouth.add("09");
        } else {
            mouth.add("10");
            mouth.add("11");
            mouth.add("12");
        }
    }

    /**
     * 根据当前日期获取季度
     *
     * @return
     * @author 黎秋荣
     * @date 2019-06-28
     */
    public static String getQuarterName(String quarterCurrent) {
        String quarterCurrentName = "";
        Integer mouth = Integer.valueOf(quarterCurrent);
        if (mouth == 1) {
            quarterCurrentName = "一季度";
        } else if (mouth == 2) {
            quarterCurrentName = "二季度";
        } else if (mouth == 3) {
            quarterCurrentName = "三季度";
        } else {
            quarterCurrentName = "四季度";
        }
        return quarterCurrentName;
    }

    /**
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param period    周期
     * @return 时间范围
     * @description 拼接日期范围内title信息
     * @author CuiShiHao
     */
    public static List<String> getRangeList(String startTime, String endTime, String period) {

        List<String> RangeList = new ArrayList<>();
        if ("年".equals(period)) {
            RangeList = DateUtils.getYearRange(startTime, endTime);
        }
        if ("月".equals(period)) {
            RangeList = DateUtils.getMonthRange(startTime, endTime);
        }
        if ("日".equals(period)) {
            RangeList = DateUtils.getDayRange(startTime, endTime);
        }
        if ("季".equals(period)) {
            RangeList = DateUtils.getSeasonRange(startTime, endTime);
        }
        return RangeList;
    }

    /**
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return java.util.List<java.lang.String> 月份
     * @description 获取一定时间范围内的所有月份（YYYYMM）
     * @author CuiShiHao
     */
    public static List<String> getMonthRange(String startTime, String endTime) {
        List<String> resultList = new ArrayList<>();
        Date startDate = parse(startTime, "yyyy-MM-dd");
        Date endDate = parse(endTime, "yyyy-MM-dd");

        //定义日期实例
        Calendar calendar = Calendar.getInstance();
        //设置日期起始时间
        calendar.setTime(endDate);

        //判断是否到结束日期
        while (calendar.getTime().after(startDate) || calendar.getTime().equals(endDate)) {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");

            String dateStr = sdf.format(calendar.getTime());
            resultList.add(dateStr);

            //进行当前日期月份减1
            calendar.add(Calendar.MONTH, -1);
        }
        return resultList;
    }

    /**
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return java.util.List<java.lang.String> 年份
     * @description 获取一定时间范围内的所有年份（YYYYMM）
     * @author CuiShiHao
     */
    public static List<String> getYearRange(String startTime, String endTime) {
        List<String> resultList = new ArrayList<>();
        Date startDate = parse(startTime, "yyyy-MM-dd");
        Date endDate = parse(endTime, "yyyy-MM-dd");

        //定义日期实例
        Calendar calendar = Calendar.getInstance();
        //设置日期起始时间
        calendar.setTime(endDate);

        //判断是否到结束日期
        while (calendar.getTime().after(startDate) || calendar.getTime().equals(endDate)) {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");

            String dateStr = sdf.format(calendar.getTime());
            resultList.add(dateStr);

            //进行当前日期月份减1
            calendar.add(Calendar.YEAR, -1);
        }
        return resultList;
    }


    /**
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return java.util.List<java.lang.String> 日期
     * @description 获取一定时间范围内的所有年份（YYYYMMDD）
     * @author CuiShiHao
     */
    public static List<String> getDayRange(String startTime, String endTime) {
        List<String> resultList = new ArrayList<>();
        Date startDate = parse(startTime, "yyyy-MM-dd");
        Date endDate = parse(endTime, "yyyy-MM-dd");

        //定义日期实例
        Calendar calendar = Calendar.getInstance();
        //设置日期起始时间
        calendar.setTime(endDate);

        //判断是否到结束日期
        while (calendar.getTime().after(startDate) || calendar.getTime().equals(endDate)) {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

            String dateStr = sdf.format(calendar.getTime());
            resultList.add(dateStr);

            //进行当前日期月份减1
            calendar.add(Calendar.DATE, -1);
        }
        return resultList;
    }


    /**
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return java.util.List<java.lang.String> 季度信息
     * @description 获取一定时间范围内的所有年份所有季度 如2018Q1,2019Q2
     * @author CuiShiHao
     */
    public static List<String> getSeasonRange(String startTime, String endTime) {
        List<String> resultList = new ArrayList<>();

        int startYear = Integer.parseInt(startTime.split("-")[0]);
        int endYear = Integer.parseInt(endTime.split("-")[0]);

        while (startYear < endYear) {
            for (int i = 1; i <= 4; i++) {
                String yearStr = startYear + "Q" + i;
                resultList.add(yearStr);
            }
            startYear++;
        }
        return resultList;
    }

    /**
     * @param endTime
     * @param period
     * @param interval
     * @return java.lang.String
     * @description 描述
     * @author CuiShiHao
     */
    public static String caculateTime(String endTime, String period, String interval) {

        Date endDate = parse(endTime, "yyyy-MM-dd");

        // 定义日期实例
        Calendar calendar = Calendar.getInstance();
        int amount = 0;
        if (!"".equals(interval)) {
            amount = Integer.parseInt("-" + interval);
        }
        // 设置日期起始时间
        calendar.setTime(endDate);
        switch (period) {
            case "年":
                calendar.add(Calendar.YEAR, amount);
                break;
            case "月":
                calendar.add(Calendar.MONTH, amount);
                break;
            case "日":
                calendar.add(Calendar.DATE, amount);
                break;
            case "季":
                calendar.add(Calendar.YEAR, 0);
                break;
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(calendar.getTime());

        return dateStr;
    }


    /**
     * @param caculDate 计算的PeriodNo
     * @param period    周期
     * @param interval  计算
     * @return String
     * @description 处理PeriodNo计算过程
     * @author CuiShiHao
     */
    public static String caculatePeriodNo(String caculDate, String period, String interval) {

        String resultdate = "";
        String dateStr = "";

        switch (period) {
            case "年":
                caculDate = dateConvertion(caculDate + "0101");
                resultdate = caculateTime(caculDate, period, interval);
                dateStr = resultdate.substring(0, 4);
                break;
            case "月":
                caculDate = dateConvertion(caculDate + "01");
                resultdate = caculateTime(caculDate, period, interval);
                dateStr = resultdate.substring(0, 4) + resultdate.substring(5, 7);
                break;
            case "日":
                caculDate = dateConvertion(caculDate);
                resultdate = caculateTime(caculDate, period, interval);
                dateStr = resultdate.substring(0, 4) + resultdate.substring(5, 7) + resultdate.substring(8, 10);
                break;
            case "季":
                // 季度数据单独处理
                String year = caculDate.substring(0, 4);
                String quarter = caculDate.substring(5, 6);
                if (Integer.parseInt(quarter) - 1 == 0) {
                    int dateYear = Integer.parseInt(year) - 1;
                    dateStr = String.valueOf(dateYear) + "Q4";
                } else {
                    int dateQuarter = Integer.parseInt(quarter) - 1;
                    dateStr = year + "Q" + String.valueOf(dateQuarter);
                }
                break;
        }

        return dateStr;
    }


    /**
     *      *@Description:日期转换，将接口返回的20180524转为2018-05-24
     *      *@author haohaounique
     *      *@Date 2018年5月24日
     *      *@param str 传递的日期字符串
     *      *@return
     *      *@exception :异常返回null
     *     
     */
    private static String dateConvertion(String str) {
        Date parse = null;
        String dateString = "";
        try {
            parse = new SimpleDateFormat("yyyyMMdd").parse(str);
            dateString = new SimpleDateFormat("yyyy-MM-dd").format(parse);
        } catch (ParseException e) {
            dateString = null;
        }
        return dateString;
    }
}
